﻿#ifndef CU_VECTOR_H_
#define CU_VECTOR_H_

#include <stdio.h>
#include <assert.h>
#include "cu.h"

template<class T>
class CuVector
{
public:
    __device__ CuVector()
    {
        m_list = nullptr;
        m_count = 0;
        m_cability = 0;
    }
    
    __device__ CuVector(const CuVector& other)
        :CuVector()
    {
        *this = other;
    }

    explicit __device__ CuVector(int size)
        :CuVector()
    {
        resize(size);
    }

    __device__ CuVector(int size, const T& value)
        :CuVector()
    {
        resize(size, value);
    }

    __device__ ~CuVector()
    {
        if (m_list)
        {
            delete[]m_list;
        }
    }

    __device__ void operator=(const CuVector& other) 
    {
        if (this == &other) 
            return; // 自赋值检查

        resize(other.m_count);
        for(int i = 0; i < other.m_count; i++)
            m_list[i] = other.m_list[i];
    }

    __device__ bool isEmpty() const
    {
        return m_count == 0;
    }

    __device__ int size() const
    {
        return m_count;
    }

    __device__ void resize(int size)
    {
        resize(size, T());
    }

    __device__ void clear()
    {
        for (int i = 0; i < m_count; i++)
            m_list[i] = T();
        m_count = 0;
    }

    __device__ void resize(int size, const T& value)
    {
        if (size < m_count)
        {
            for (int i = size; i < m_count; i++)
                m_list[i] = T();
        }
        else if (size == m_count)
        {
            return;
        }
        else
        {
            reserve(size);
            for (int i = m_count; i < size; i++)
                m_list[i] = value;
        }
        m_count = size;
    }

    __device__ int indexOf(const T& value) const
    {
        for (int i = 0; i < m_count; i++)
        {
            if (m_list[i] == value)
                return i;
        }
        return -1;
    }

    __device__ bool contains(const T& value) const
    {
        return indexOf(value) >= 0;
    }

    __device__ void reverse()
    {
        for (int i = 0; i < m_count / 2; i++)
        {
            auto tmp = m_list[i];
            m_list[i] = m_list[m_count - i - 1];
            m_list[m_count - i - 1] = tmp;
        }
    }

    __device__ void insert(int index,T t)
    {
        assert(index >= 0 && index <= size());
        resize(m_count + 1);
        for(int i = m_count - 1; i > index; i--)
            m_list[i] = m_list[i - 1];

        m_list[index] = t;
    }

    __device__ void push_back(T t)
    {
        reserve(m_count + 1);
        m_list[m_count] = t;
        m_count++;
    }

    __device__ void pop_back()
    {
        assert(m_count > 0);
        m_list[m_count - 1] = T();
        m_count--;
    }

    T& front()
    {
        assert(m_count > 0);
        return m_list[0];
    }

    T &back()
    {
        assert(m_count > 0);
        return m_list[m_count - 1];
    }

    __device__ T& operator[](int index)
    {
        assert(index >= 0 && index < m_count);
        return m_list[index];
    }

    __device__ const T& operator[](int index) const
    {
        assert(index >= 0 && index < m_count);
        return m_list[index];
    }
    
    __device__  T* data()
    {
        return m_list;
    }

    __device__ const T* data() const
    {
        return m_list;
    }

    __device__ void append(const CuVector<T>& vec)
    {
        reserve(m_count + vec.size());
        for (int i = 0; i < vec.size(); i++)
        {
            m_list[m_count + i] = vec[i];
        }
        m_count = m_count + vec.size();
    }

    __device__ CuVector<T> mid(int start, int len = -1) const
    {
        if (len == -1)
            len = m_count - start;
        if (start + len > m_count)
            len = m_count - start;
        assert(start >= 0 && len >= 0);

        CuVector<T> ret(len);
        for (int i = 0; i < ret.size(); i++)
        {
            ret.m_list[i] = m_list[start + i];
        }
        return ret;
    }

    __device__ void reserve(int size)
    {
        if (m_cability > size)
            return;

        if (m_cability == 0)
            m_cability = 8;
        while (m_cability < size)
            m_cability *= 2;

        T* new_list = new T[m_cability];
        if (m_list)
        {
            for (int i = 0; i < m_count; i++)
                new_list[i] = m_list[i];
            
            delete[]m_list;

        }
        m_list = new_list;
    }

    T* m_list;
    int m_count;
    int m_cability;
};


typedef CuVector<char> CuByteArray;
__device__ CuByteArray toBytes(const char *,int size);

#endif